package com.wang.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wang.feign.CouponFeignService;
import com.wang.interceptor.LoginInterceptor;
import com.wang.model.LoginUser;
import com.wang.request.NewUserCouponRequest;
import com.wang.request.UserLoginRequest;
import com.wang.request.UserRegisterRequest;
import com.wang.enums.BizCodeEnum;
import com.wang.enums.SendCodeEnum;
import com.wang.mapper.UserMapper;
import com.wang.model.UserDO;
import com.wang.service.NotifyService;
import com.wang.service.UserService;
import com.wang.util.CommonUtil;
import com.wang.util.JWTUtil;
import com.wang.util.JsonData;
import com.wang.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.Md5Crypt;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Autowired
    private CouponFeignService couponFeignService;

    @Autowired
    private UserMapper userMapper;


    @Autowired
    private NotifyService notifyService;

    /**
     * 用户注册:
     *  1.邮箱验证码校验
     *  2.密码加密（TODO）   TODO表示相关功能代码还没写完，需要后续补充
     *  3.账号唯一性检查(TODO)
     *  4.插入数据库
     *  5.新注册用户福利发送(TODO)
     * @param userRegisterRequest
     * @return
     */
    @Transactional(rollbackFor=Exception.class,propagation= Propagation.REQUIRED)
    //@GlobalTransactional
    @Override
    public JsonData register(UserRegisterRequest userRegisterRequest) {
        boolean checkCode = false;
        if(StringUtils.isNotBlank(userRegisterRequest.getMail())){
            checkCode = notifyService.checkCode(SendCodeEnum.USER_REGISTER, userRegisterRequest.getMail(), userRegisterRequest.getCode());
        }
        if(checkCode){
            return JsonData.buildResult(BizCodeEnum.CODE_ERROR);
        }
        UserDO userDO = new UserDO();
        BeanUtils.copyProperties(userRegisterRequest,userDO);//属性复制

        userDO.setCreateTime(new Date());
        userDO.setSlogan("落日孤城闭，决战长安京！");


        //设置密码 TODO     $1$表示加密方式(表示MD5加密)，后面接盐值，随机8位字符串
        //生成秘钥
        userDO.setSecret("$1$"+CommonUtil.getStringNumRandom(8));
        //密码 + 加盐处理
        String cryptPwd = Md5Crypt.md5Crypt(userRegisterRequest.getPwd().getBytes(),userDO.getSecret());
        userDO.setPwd(cryptPwd);

        //账号唯一性检查 TODO   代码层面较难保证，多线程，高并发的情况。解决方法之一：在数据库层面做唯一性检查（在相应关键字添加唯一约束）
        if(checkUnique(userDO.getMail())){
            int rows = userMapper.insert(userDO);
            log.info("用户注册结果：{},注册成功",rows,userDO);

            //新用户注册成功，初始化信息，福利发送等 TODO
            userRegisterInitTask(userDO);

            return JsonData.buildSuccess();
        }else{
           return JsonData.buildResult(BizCodeEnum.ACCOUNT_REPEAT);
        }

    }

    /**
     * 用户登录
     *  1.根据Mail去查找是否存在该用户
     *  2.判断密码是否正确
     * @param userLoginRequest
     * @return
     */
    @Override
    public JsonData login(UserLoginRequest userLoginRequest) {
        QueryWrapper<UserDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mail",userLoginRequest.getMail());
        List<UserDO> userDO = userMapper.selectList(queryWrapper);
        //判断用户是否存在
        if(userDO != null && userDO.size() == 1){
            //判断密码是否正确
            if(userDO.get(0).getPwd().equals(Md5Crypt.md5Crypt(userLoginRequest.getPwd().getBytes(),userDO.get(0).getSecret()))){
                //生成token令牌 TODO
                LoginUser userDTO = LoginUser.builder().build();
                BeanUtils.copyProperties(userDO.get(0), userDTO);
                String token = JWTUtil.geneJsonWebToken(userDTO);

                return JsonData.buildSuccess(token);
            }else{
                return JsonData.buildResult(BizCodeEnum.ACCOUNT_PWD_ERROR);
            }
        }else{
            return JsonData.buildResult(BizCodeEnum.ACCOUNT_UNREGISTER);
        }
    }

    /**
     *
     * @return
     */
    @Override
    public UserVO findUserDetail() {
        //有拦截器，可以通过ThreadLocal(拦截器保存了token中的用户信息到ThreadLocal中)获取用户信息
        LoginUser loginUser = LoginInterceptor.threadLocal.get();
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(loginUser,userVO);
        return userVO;
    }

    /**
     * 账号唯一性检查
     * @param mail
     * @return
     */
    private boolean checkUnique(String mail) {
        QueryWrapper<UserDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mail",mail);
        if(userMapper.selectCount(queryWrapper)==0){
            return true;
        }else{
            return false;
        }
    }


    /**
     * 新用户注册，发送福利
     * @param userDO
     */
    private void userRegisterInitTask(UserDO userDO){
        NewUserCouponRequest newUserCouponRequest = new NewUserCouponRequest();
        newUserCouponRequest.setUserID(userDO.getId());
        newUserCouponRequest.setName(userDO.getName());
        JsonData jsonData = couponFeignService.newUserCoupon(newUserCouponRequest);
        /*if(jsonData.getCode() != 0){
            throw new RuntimeException("新人优惠券发放失败");
        }*/
        log.info("新人优惠券发放成功");
    }
}
